#pragma once
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace  std;

struct Point3D {
    double x, y,  z;
    int index;
   
};

struct NormalizeData {

    NormalizeData() {}

    void normalizePoints(std::vector<Point3D>& points) {
        if (points.empty()) return;

        // Step 1: Determine the bounding box
        double xMin = points[0].x, xMax = points[0].x;
        double yMin = points[0].y, yMax = points[0].y;
        double zMin = points[0].z, zMax = points[0].z;

        for (const auto& point : points) {
            xMin = std::min(xMin, point.x);
            xMax = std::max(xMax, point.x);
            yMin = std::min(yMin, point.y);
            yMax = std::max(yMax, point.y);
            zMin = std::min(zMin, point.z);
            zMax = std::max(zMax, point.z);
        }

        // Step 2: Calculate the center and translate
        double cx = (xMin + xMax) / 2.0;
        double cy = (yMin + yMax) / 2.0;
        double cz = (zMin + zMax) / 2.0;

        for (auto& point : points) {
            point.x -= cx;
            point.y -= cy;
            point.z -= cz;
        }

        // Step 3: Scale to unit size
        double L = std::max({ xMax - xMin, yMax - yMin, zMax - zMin });
        if (L == 0) L = 1; // Avoid division by zero

        for (auto& point : points) {
            point.x /= L;
            point.y /= L;
            point.z /= L;
        }
    }

    void generateDataWidthNoIndex(const string& path, const string& filename) {
    
        string path_name = path + filename;
        std::ifstream inputFile(path_name);
        string output_name = path + filename.substr(0, filename.size() - 4)+"_norm.txt";
        std::ofstream outputFile(output_name);
        std::vector<Point3D> points;
        double x, y, z;
        int index;

        // Read points from input file
        if (!inputFile.is_open()) {
            std::cerr << "Failed to open input file." << std::endl;
            return;
        }

        std::cout << "Start reading points..." << std::endl;
        string line;
        getline(inputFile, line);
        while (inputFile >> x >> y >> z) {
           
            points.push_back({ x, y, z });
        }


        std::cout << "Finished reading points. Total: " << points.size() << std::endl;

        // Normalize points
        normalizePoints(points);

        // Write normalized points to output file
        if (!outputFile.is_open()) {
            std::cerr << "Failed to open output file." << std::endl;
            return;
        }

        std::cout << "Start writing normalized points..." << std::endl;
        for (const auto& point : points) {
            outputFile << point.x << " " << point.y << " "  << point.z << "\n";
        }
        std::cout << "Finished writing normalized points." << std::endl;

        inputFile.close();
        outputFile.close();

        std::cout << "Normalization complete. Check output.txt for results.\n";
    
    }


    void generateData() {

        std::ifstream inputFile("D:/wins-desktop/pcl_geo1/dat/fault.txt");
        std::ofstream outputFile("fault_output.txt");
        std::vector<Point3D> points;
        double x, y, z;
        int index;

        // Read points from input file
        if (!inputFile.is_open()) {
            std::cerr << "Failed to open input file." << std::endl;
            return ;
        }

        std::cout << "Start reading points..." << std::endl;
        string line;
        getline(inputFile, line);
        while (inputFile >> x >>  y >> index >> z) {
            std::cout << "------------------" << index << std::endl;
            points.push_back({ x, y, z,index });
        }
       
       
        std::cout << "Finished reading points. Total: " << points.size() << std::endl;

        // Normalize points
        normalizePoints(points);

        // Write normalized points to output file
        if (!outputFile.is_open()) {
            std::cerr << "Failed to open output file." << std::endl;
            return ;
        }

        std::cout << "Start writing normalized points..." << std::endl;
        for (const auto& point : points) {
            outputFile << point.x << " " << point.y << " " << point.index << " " << point.z << "\n";
        }
        std::cout << "Finished writing normalized points." << std::endl;

        inputFile.close();
        outputFile.close();

        std::cout << "Normalization complete. Check output.txt for results.\n";

    }

};